package cn.clq.basic.service.impl;

import cn.clq.basic.constant.Constant;
import cn.clq.basic.dto.RegisterDto;
import cn.clq.basic.exception.BusinessException;
import cn.clq.basic.service.IVerifyCodeService;
import cn.clq.basic.util.MailUtils;
import cn.clq.basic.util.StrUtils;
import cn.clq.basic.util.VerifyCodeUtils;
import cn.clq.user.domain.User;
import cn.clq.user.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
 * @author clqlongbao
 * @version 1.0
 * @description: TODO
 * @date 2022/6/15 19:14
 */
@Service
public class VerifyCodeServiceImpl implements IVerifyCodeService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserMapper userMapper;


    /**
     * @description:发送图形验证码
     * @param: key
     * @return: java.lang.String
     * @author clqlongbao
     * @date: 2022/6/16 21:07
     */
    @Override
    public String imageCode(String uuid) {
        if (StringUtils.isEmpty(uuid)) {
            throw new BusinessException("key不能为空！！！");
        }
        //产生验证码的位数
        String code = StrUtils.getComplexRandomString(4);
        //将数据保存到redis，设置过期时间  key是uuid
        redisTemplate.opsForValue().set(
                uuid,//前端传递的UUID
                code, //图片中显示的码
                5,//过期时间
                TimeUnit.MINUTES);//过期时间的单位
        //使用2D引擎把code画成图
        //把图使用Base64编码成字符串
        //返回Base64编码的字符串
        return VerifyCodeUtils.VerifyCode(100, 38, code);
    }


    /**
     * @description: 发送短信验证码
     * @param: dto
     * @return: void
     * @author clqlongbao
     * @date: 2022/6/16 20:57
     */
    @Override
    public void sendSmsCode(RegisterDto dto) {
//        一：校验
//        1.空校验
        String phone = dto.getPhone();
        String imageCode = dto.getImageCode();
        String uuid = dto.getUuid();
        System.out.println(phone);
        System.out.println(imageCode);
        System.out.println(uuid);
        if(phone==null || imageCode==null || uuid==null){
            throw new BusinessException("请填写完整信息");
        }
//        2.校验图形验证码，根据uuid从redis获取图形验证码
        String imageCodeTmp = (String) redisTemplate.opsForValue().get(uuid);
//  。获取不到 图形验证码过期，重新获取
        if(imageCodeTmp==null){
            throw new BusinessException("图形验证码已过期，请重新获取");
        }
//  。获取到了，比对图形验证码是否正确
//                - 不正确，提示输入图形验证码错误
//                - 正确，往下走
        if(!imageCodeTmp.equalsIgnoreCase(imageCode)){
            throw new BusinessException("图片验证码错误，请重新输入");
        }
//        3.校验手机号是否注册过了
        User user = userMapper.loadByPhone(phone);
//  。注册过了，滚去登录
        if(user!=null){
            throw new BusinessException("手机号已被注册，请直接登录或者更换手机号");
        }
//  。没有注册过，往下走
//        二：短信验证码逻辑
//        1.根据手机号拼接key，159:register，从redis获取曾今可能发送的短信验证码
        String smsCodeKey = phone+ Constant.SmsCode.REGISTER_SUFFIX;
        String smsCodeTmp = (String) redisTemplate.opsForValue().get(smsCodeKey);
//        1.1 获取到了
        String smsCode = null;
        if(smsCodeTmp!=null){

//        1.1.1 校验是否过了一分钟重发时间 value  9527:232468742341657213
            Long oldTime =Long.valueOf( smsCodeTmp.split(":")[1]);
            //两个时间戳的间隔
            Long interval = System.currentTimeMillis() - oldTime;
            if(interval<1*60*1000){
//	   。小于一分钟  同行搞事
                throw new BusinessException("已拒绝非法访问！！！");
           }
//	   。大于一分中 （还没有到3分钟，验证码还有效），
//        使用还没过期的验证码，刷新过期时间
            smsCode=smsCodeTmp.split(":")[0];
        }else{
//        1.2 获取不到
//        1.2.1.生成新的短信验证码
            smsCode = StrUtils.getComplexRandomString(4);
        }
        String smsCodeVaue = smsCode + ":" + System.currentTimeMillis();

//        3.存储redis 设置一个过期时间
        redisTemplate.opsForValue().set(smsCodeKey,smsCodeVaue,3,TimeUnit.MINUTES);
//        4.发送短信
        //SmsUtils.sendSms(phone,"亲，您的验证码是：" + smsCode + "3分钟内有效。您正在使用登录功能，请勿向他人转发或泄漏此验证码！！！");
        System.out.println(Constant.SmsCode.CONTENT_PREFIX + smsCode + Constant.SmsCode.CONTENT_SUFFIX);
    }
}
